Skip to content

[Perf][SM70] Add opt-in native-g32 AWQ QPN M1 dispatch - #521

Merged
yangzhuxinyzx merged 9 commits into
1CatAI:mainfrom
Leonccaa:perf/sm70-awq-qpn-m1-runtime-main-20260906
Sep 6, 2026
Merged

yangzhuxinyzx merged 9 commits into
1CatAI:mainfrom
Leonccaa:perf/sm70-awq-qpn-m1-runtime-main-20260906

Conversation

@Leonccaa

@Leonccaa Leonccaa commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Purpose

Connect the AWQ M=1 operator from #519 to a narrow, default-off runtime route for Qwen3.8 TP4 single-token decode, and record the full-model evidence for it.

Depends on #519 (the operator) and #520 (the layer contract helper and the grouped 2 to 8 token baseline both arms ran on). This branch contains both so it can be built and tested as a whole; the commits specific to this PR are the last two, 4d95867e3e (dispatch) and 356c1bafff (acceptance documentation). The rest of the diff disappears once #519 and #520 merge.

  • Add VLLM_SM70_AWQ_QWEN38_QPN_M1, default 0, accepting only 0 or 1.
  • At initialization, require the TP4 / E512 / native and prepared group-32 contract, the batched TurboMind banks, interleaved W13 and the legacy single-token compact admission. An explicit opt-in on an unsupported layer, or on a build without the native operator, fails closed.
  • At execution, only a physical single token selects the route: contiguous FP16 (1, 2560) input, INT32 (1, 10) expert IDs, FP32 (1, 10) router weights. Every other physical batch shape, including padded CUDA Graph batches, keeps its existing route.
  • Reuse the existing prepared banks and the existing intermediate and output buffers. No DSO loading, no compilation at startup, no additional weight copy, no change to grouped decode, prefill, router, shared experts, attention, graph policy or MTP.
  • Rollback: set the flag to 0 and restart; changing the variable cannot replace an already captured graph.

Full-model performance

4x Tesla V100 PCIe 32 GB, TP4/MTP0, FP16 activations and KV, native-group-32 AWQ checkpoint, 4-byte metadata, frozen prompt token IDs, prefix cache off, 8192 max batched tokens, ignore_eos=false, 320 output tokens, one score per cell and arm. Both arms include #520's grouped-decode route and the same separately tracked QSA page4 fix (#494). Pure aggregate decode tok/s over the common all-active window:

Cell QPN off QPN on
C1 x 64K 50.03 59.03
C4 x 64K 131.35 129.54
C8 x 16K 246.36 245.78

C1 gains 18.0% in this pair; the same-day NVFP4 reference on the same contract was 60.26 tok/s, so the remaining gap is about 2.0%. An earlier prototype pair on the same contract measured 51.50 to 59.16 tok/s. C4 and C8 do not take this route except in a one-token drain tail and are unchanged within run-to-run noise.

Per-step GPU service time, averaged over ranks, from the traces of the prototype pair: W13 1.418 to 0.736 ms, W2 including weighted reduction 1.139 to 0.505 ms, the format-specific prepare kernel 0.988 ms to absent; QSA, HC and shared-expert gate unchanged. All 48 layers hit the new W13/W2 kernels; the old prepare and standalone reduce kernels are absent from every graph.

Memory after startup is identical between arms on all four ranks: 563 KV blocks, 5,762,813,952 KV bytes, 28,605,358,080 PyTorch allocated bytes per rank.

Numerical acceptance

Both paths approximate the same fixed AWQ-weight computation and neither is ground truth. Each was compared against the same independently decoded-weight FP64 reference; holding the checkpoint fixed separates this change's arithmetic perturbation from the quantization error present in both.

  • 1,152 captured layer/rank/arm samples at three fixed prefixes: both implementations' W13 and W2 stay within the retained rounding bounds (maximum bound fraction QPN 0.174/0.966, legacy 0.174/0.954).
  • Same-runtime 65-case quality pair, official scoring, natural EOS:
Subset QPN off QPN on
HumanEval 5/5 5/5
MBPP 4/5 4/5
IFEval strict 3/5 4/5
GSM8K 29/32 28/32
Tool selection 10/12 10/12
Needle retrieval 6/6 6/6

47/65 output token streams are identical. One GSM8K regression and one IFEval improvement remain and are not netted against each other; this is not a zero-regression or statistical non-inferiority result.

  • The GSM8K divergence is attributable: at output index 120 the legacy logits for token IDs 4003 and 16526 are exactly tied at 21.59375, while the QPN path gives 21.625 and 21.578125, one to two FP16 steps apart, and the later tokens follow. The legacy path itself reproduced the failed answer at the same 256-token budget in a repeat, so the failure is not exclusive to the new kernel. At a captured 64K step, 13 of 48 layers change expert membership within their own router scores; the first change reverses a 0.0117 score margin, so global logit differences (maximum 1.75 in the focused capture, 5.05 in an earlier full trace) are larger than the local rounding error.
  • The analysis tool was corrected to use argmax rather than the first index of topk(2) at ties; raw tensors and scores did not change.

Current evidence supports numerical trajectory variation without a systematic kernel defect on the tested inputs. It does not establish broad quality non-inferiority or production readiness, which is why the route is opt-in.

Duplicate-work check

Open-PR searches on 2026-09-06 in 1CatAI/1Cat-vLLM for "AWQ QPN", "QPN M1", "awq_qpn", "AWQ M1" and "Qwen3.8 AWQ decode" found no competing AWQ single-token route. #510 tunes the NVFP4 M=1 kernel; #509 is conversion-cache release; #504 is NVFP4 batched work. Base is main@755baae1d0.

Tests

  • CPU on this branch: tests/quantization/test_awq_qpn_sm70.py, test_sm70_awq_active_grouped_decode.py, test_sm70_awq_indexed_prefill.py, test_sm70_awq_compact_metadata.py: 69 passed. Covers default-off never touching the native lookup, rejected flag values, unsupported layers failing closed, missing native build failing closed, both metadata layouts, no sidecar loading, single-physical-token admission across 0/1/2/4/5/8/128/8192 tokens, dtype and stride rejection, rollback, and the real MoE branch calling the native op with the existing banks.
  • Pre-commit on the changed files, including mypy, and git diff --check: clean.
  • The runtime Python files are the same commits that produced the GPU-validated build; the native core used for the full-model pair is e5083c1f...8916e1.

Provenance

Fork review draft: Leonccaa#12 (same commits, rebased onto #520 plus the same operator change as #519). Design and acceptance notes: docs/design/sm70_awq_qpn_m1.md.

AI assistance was used. OpenAI Codex implemented the dispatch, tests, attribution and evidence under Leon's direction; Claude Code reviewed the diff, re-ran the CPU tests and pre-commit on this branch, and prepared this submission. Human review is still required.

🤖 Generated with Claude Code

Reuse the existing active-stage operator for TP4 g32 M2-8 decode, align warmup admission, and annotate scratch mutations. Keep C1 and unmatched contracts on existing routes; add focused coverage without new public operators or GEMM kernels.

Validated with 51 GPU-directed tests, 32 dynamic-route operator comparisons, and QSA-fixed matched model runs. Single-run pure-decode gains: C4x64K +5.62%, C8x16K +2.24%. Natural-EOS AWQ outputs match 17/18; the retained and/+ near-tie and W13 rounding differences are not claimed bitwise exact. No precision-default changes or deployment.

Co-authored-by: OpenAI Codex
Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Separate implementation-only and existing-autotune gains; document EOS rounding limitations, capacity and startup observations, rollback, and the dual-format C1 follow-up.

Co-authored-by: OpenAI Codex

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Record the new main integration gate separately from frozen GPU results; keep prefill and grouped decode admission disjoint.

Co-authored-by: OpenAI Codex

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Co-authored-by: OpenAI Codex

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Assisted-by: OpenAI Codex

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Use the retained engine log instead of extrapolating cache block count. No production or benchmark changes.

Co-authored-by: OpenAI Codex <noreply@openai.com>

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Add the typed inference operator, prepared-bank decoder, FP32 reduction kernels and standalone GPU tests without changing model dispatch. Keep 3B scalar loading here so cooperative metadata access can be reviewed separately.

Assisted-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
(cherry picked from commit 27a27d3)
(cherry picked from commit 5b4135f)
Gate the native operator to the existing Qwen3.8 TP4 E512 M1 contract, retaining default-off behavior and neighboring routes. Document numerical attribution, observed quality changes, and incomplete production acceptance.

Assisted-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
(cherry picked from commit 37fb5d2)
Evaluate both AWQ arithmetic paths against an independent fixed-weight reference; distinguish existing quantization error, local arithmetic bounds, and task-level quality.

Assisted-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
(cherry picked from commit 6f73eac)
@Leonccaa

Leonccaa commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Fresh QPN runtime OFF/ON regression (2026-09-06 UTC)

Reviewed #521 head 356c1bafff769d8bb1a48f8402703333ff6c45e7. Model tests
use the same exact rebuilt public #522 stack in both arms, head
9c5b69950e62f48840ed0b959e79d9f7a9a6bd12, with an engine restart for each
setting. Source archives and actual worker-loaded native/Flash/QSA hashes
were checked; no sidecar/JIT operator or #494/#509/#523 overlay was loaded.

The later #522 default-switch commit 9e23886bdc is covered separately.
Both QPN arms below explicitly use 4B; the earlier frozen head and measured
data are not relabeled as the newer 3B-default deployment.

The only intended configuration change is
VLLM_SM70_AWQ_QWEN38_QPN_M1=0 -> 1. Grouped M2–8 stays ON, optional
small-shape tuning stays OFF, and metadata stays 4B. All four workers verified
48/48 QPN-enabled layers in ON versus 0/48 in OFF, with the same prepared
banks/buffers. The flag remains default OFF in the product.

Matched contract: 4 x V100 32GB / TP4, FP16 activation/KV, MTP0, frozen AWQ
checkpoint and prompt token IDs, chunk 8192, prefix cache/async scheduling
off, FULL_AND_PIECEWISE graphs. One scored run after warmup per cell,
320-token cap, ignore_eos=false, min_tokens=0.

Cell Online pure-decode total tok/s OFF -> ON Change Batch E2E seconds OFF -> ON
C1 x 64K 51.4864 -> 59.2099 +15.00% 20.9666 -> 19.8932
C4 x 64K 117.4943 -> 117.7127 +0.19% 90.6454 -> 90.6700
C8 x 16K 212.5878 -> 212.8465 +0.12% 42.9427 -> 42.9054

These are engine-output all-active serving-decode rates, including the
normal sampling/runtime path, not isolated llama-bench TG rates. One common
interval is used for every request: last first-output delivery through first
completion delivery. Newly delivered tokens in it are counted once, excluding
the first-token boundary: 319 / 294 / 304 per request for the three cells.
All 13 complete performance output sequences matched across arms. No repeated
score selection or statistical significance claim; no fresh NVFP4 arm was run.

Quality and numerical evidence

Across 65 frozen quality records, all per-record task scores were unchanged;
50/65 complete token sequences matched. Both scored HumanEval 5/5, MBPP 4/5,
IFEval strict prompts 4/5 and instructions 10/12, GSM8K 29/32, local tool-choice
coarse checks 10/12, and 1K–128K needle checks 6/6. This is a bounded paired
screen, not full-suite or statistical non-inferiority evidence. Code evaluation
ran in a CPU-only, read-only, network-disabled sandbox using the pinned scorer.

An already-incorrect MBPP record changed from natural stop to the fixed output
cap. The default arm also already has two stop-to-length changes relative to
the grouped-disabled arm, described in the #520 addendum. Unchanged task
scores therefore do not mean no added truncations or unconditional quality
acceptance.

All fixed-prefix raw logits were finite, with same-arm A/A exactly equal
(70 rows per arm). Cross-process C1 x 64K: maximum absolute difference
6.775390625, RMS 0.2562685, p99 absolute difference 0.9418945, 0/320 argmax
changes. Unchanged C4 routes also differed across processes (one short case
maximum 4.40625), so this is not a uniquely isolated QPN error measurement.
The public freeze lacks the open #494 allocation-order repair, and startup
kernel choices are not established identical. The independent native FP64
stage bounds passed, but they do not justify blanket acceptance of arbitrary
whole-model logit differences. No new numerical threshold was fitted.

Ready live allocation and KV were unchanged: 28,605,358,080 allocated bytes,
29,848,764,416 reserved bytes, 563 KV blocks per rank. Sampled QPN-ON startup
peaks were 31.863–31.886 GiB (requested 50 ms telemetry; observed maximum gap
420.45 ms), so sub-sample peaks and co-hosting headroom are not established.

Startup-peak clarification: neither tested #522 snapshot includes the still-open
#509 loading-cache fix.
That fix already has separate paired AWQ/NVFP4 validation. The near-32-GiB
observations here are from builds without it, not evidence that the fix failed
or that this PR introduced a new loading-peak defect. This long-context stack
has not been remeasured with #509; its earlier reduction cannot simply be
subtracted from these peaks.

Both full-model captures and sandbox scoring exited successfully. Shutdown
resource-tracker warnings were retained; GPU compute processes exited before
the next arm. Native tests and 209 adjacent SM70 tests are detailed in the
#519 addendum. Further optional-tuning/3B results are documented separately;
they must not be silently included in the +15.00% QPN-only figure.

For completeness, optional small-shape tuning ON (still 4B/QPN ON) measured
C1/C4/C8 online pure-decode rates 59.0934/131.3053/245.4491 tok/s, or
-0.20%/+11.55%/+15.32% relative to the QPN-ON/tuning-OFF arm. Its 13
performance outputs matched; this arm had short natural-EOS smoke plus
performance coverage, not another 65-case/teacher-forcing quality run.
Those optional-tuning gains are not caused solely by this QPN-M1 switch.

AI assistance: Codex executed the regression and prepared this addendum at
Leon's request. No product edits, new optimization, independent maintainer
approval, or upstream GPU CI result are claimed.

@yangzhuxinyzx
yangzhuxinyzx merged commit 356c1ba into 1CatAI:main Sep 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants